import base64
import pickle

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.generics import CreateAPIView
from django_redis import get_redis_connection

# Create your views here.
from carts.serializers import CartSerializer, CartSKUSerializer, CartDelSerializer, CartSelectedSerializer
from goods.models import SKU


class CartView(APIView):
    """添加商品到购物车"""

    def perform_authentication(self, request):
        """重写父类的用户验证方法,不在进入视图前就检查jwt"""
        pass

    def post(self, request):
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.validated_data.get('sku_id')
        count = serializer.validated_data.get('count')
        selected = serializer.validated_data.get('selected')
        try:
            user = request.user
        except:
            user = None

        if user is not None and user.is_authenticated:
            # 用户已经登录
            conn = get_redis_connection('cart')
            pl = conn.pipeline()

            pl.hincrby('cart_%s' % user.id, sku_id, count)

            if selected:
                pl.sadd('cart_select_%s' % user.id, sku_id)
            pl.execute()
            return Response(serializer.data, status=201)
        else:
            # 用户未登录
            cart = request.COOKIES.get('cart')
            if cart is not None:
                cart = pickle.loads(base64.b64decode(cart.encode()))

            else:
                cart = {}

            sku = cart.get(sku_id)

            if sku:
                count += int(sku.get('count'))

            cart[sku_id] = {
                'count': count,
                'selected': selected

            }
            cookie_cart = base64.b64encode(pickle.dumps(cart)).decode()
            response = Response(serializer.data, status=201)
            response.set_cookie('cart', cookie_cart, max_age=60 * 60 * 24)
            return response

    def get(self, request):
        """展示购物车中的信息"""
        try:
            user = request.user
        except:
            user = None
        # user = request.user if request.user else None

        if user and user.is_authenticated:
            # 已经登录的用户则把数据取出来
            # 连接redis
            conn = get_redis_connection('cart')
            carts = conn.hgetall('cart_%s' % user.id)
            cart_selected = conn.smembers('cart_select_%s' % user.id)
            cart = {}
            for sku_id, count in carts.items():
                cart[int(sku_id)] = {
                    'count': count,
                    'selected': sku_id in cart_selected
                }

        else:
            # 用户未登录
            cart = request.COOKIES.get('cart')
            if cart:
                cart = pickle.loads(base64.b64decode(cart.encode()))
            else:
                cart = {}

        skus = SKU.objects.filter(id__in=cart.keys())
        for sku in skus:
            sku.count = cart[sku.id]['count']
            sku.selected = cart[sku.id]['selected']
        serializer = CartSKUSerializer(skus, many=True)
        return Response(serializer.data)

    def put(self, request):
        """修改购物车数据"""
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.validated_data.get('sku_id')
        count = serializer.validated_data.get('count')
        selected = serializer.validated_data.get('selected')

        # 尝试对请求的用户进行验证
        try:
            user = request.user
        except Exception:
            user = None

        if user and user.is_authenticated:
            conn = get_redis_connection('cart')
            pl = conn.pipeline()
            # hset命令用于为哈希表中的字段赋值 如果不存在则创建哈希表,存在则覆盖旧值
            pl.hset('cart_%s' % user.id, sku_id, count)

            if selected:
                # Redis Sadd 命令将一个或多个成员元素加入到集合中，已经存在于集合的成员元素将被忽略。
                pl.sadd('cart_select_%s' % user.id, sku_id)
            else:
                pl.srem('cart_select_%s' % user.id, sku_id)

            pl.execute()
            return Response(serializer.data)
        else:
            cart = request.COOKIES.get('cart')

            try:
                cart = pickle.loads(base64.b64decode(cart.encode()))
            except:
                cart = {}

            # sku = cart.get(sku_id)
            #
            # if sku:
            #     count += int(sku.get('count'))

            cart[sku_id] = {
                'count': count,
                'selected': selected

            }
            cookie_cart = base64.b64encode(pickle.dumps(cart)).decode()
            response = Response(serializer.data)
            response.set_cookie('cart', cookie_cart, max_age=60 * 60 * 24)
            return response

    def delete(self, request):
        """删除数据"""
        # 获取sku_id
        serializer = CartDelSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        sku_id = serializer.validated_data.get('sku_id')
        try:
            user = request.user
        except:
            user = None

        if user is not None and user.is_authenticated:
            # 用户已经登录
            conn = get_redis_connection('cart')
            sku_dict = conn.hgetall('cart_%s' % user.id)  # {'13':'1','15':'1'}

            for sku_list in sku_dict.keys():
                if sku_id == int(sku_list):
                    conn.hdel('cart_%s' % user.id, sku_list)

            conn.srem('cart_select_%s' % user.id, sku_id)
            return Response(serializer.data)
        else:
            # 用户未登录
            response = Response(status=204)
            cart = request.COOKIES.get('cart')
            if cart is not None:
                cart = pickle.loads(base64.b64decode(cart.encode()))

            else:
                cart = {}

            if sku_id in cart:
                del cart[sku_id]
                cookie_cart = base64.b64encode(pickle.dumps(cart)).decode()
                response = Response(serializer.data)
                response.set_cookie('cart', cookie_cart, max_age=60 * 60 * 24)
            return response


class CartSelectedView(APIView):
    def perform_authentication(self, request):
        """重写父类的用户验证方法,不在进入视图前就检查jwt"""
        pass

    def put(self, request):
        serializer = CartSelectedSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        selected = serializer.validated_data.get('selected')
        response = Response(serializer.data)
        # 连接redis

        try:
            user = request.user
        except:
            user = None

        if user and user.is_authenticated:
            conn = get_redis_connection('cart')

            if selected:
                sku_dict = conn.hgetall('cart_%s' % user.id)
                for sku_id in sku_dict.keys():
                    conn.sadd('cart_select_%s' % user.id, int(sku_id))

            else:
                selected_list = conn.smembers('cart_select_%s' % user.id)
                print(selected_list)
                for selected_id in selected_list:
                    conn.srem('cart_select_%s' % user.id, selected_id)

        else:
            # 用户未登录
            cart = request.COOKIES.get('cart')

            if cart is not None:
                # 解密
                cart = pickle.loads(base64.b64decode(cart.encode()))

                for sku_id in cart.keys():
                    cart[sku_id] = {
                        'selected': selected
                    }
                    # 在cookie中的数据一定要先加密才能存放
                    cookie_cart = base64.b64encode(pickle.dumps(cart)).decode()
                    response = Response(serializer.data)
                    # 如果不设置有效期则当关闭会话就会失效
                    response.set_cookie('cart', cookie_cart, max_age=60 * 60 * 24)


        return response
